<script setup lang="ts">
import { vLoading } from 'element-plus'
import 'element-plus/es/components/loading/style/css'
import { omit } from 'lodash-es'

import {
  Close,
  Minus,
  Plus,
} from '@element-plus/icons-vue'
import AsyncComponent from './AsyncComponent.vue'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(
  defineProps<{
    title: string
    showFooter?: boolean
    showCancelButton?: boolean
    showConfirmButton?: boolean
    cancelButtonText?: string
    confirmButtonText?: string
    needSaving?: boolean
    drag?: boolean
    beforeClose?: (done: () => void) => void
    fullable?: boolean
    noMaxHeight?: boolean
  }>(),
  {
    needSaving: false,
    showFooter: true,
    showCancelButton: true,
    showConfirmButton: true,
    cancelButtonText: '取消',
    confirmButtonText: '保存',
    drag: true,
    fullable: false,
    beforeClose: undefined,
  },
)

const emits = defineEmits<{
  (e: 'confirm', done: () => void): void
  (e: 'close'): void
  (e: 'fullscreen', bol: boolean): void
}>()
const visible = ref(false)
const [saving, setSaving] = useState(false)
const [draggable, setDraggable] = useState(props.drag)

function open() {
  visible.value = true
}
function close() {
  if (props.needSaving && saving.value)
    return
  const handler = () => {
    visible.value = false
    emits('close')
  }
  if (props.beforeClose) {
    props.beforeClose?.(handler)
  }
  else {
    handler()
  }
}

async function confirmHandler() {
  setSaving(true)
  emits('confirm', () => {
    setSaving(false)
  })
}

defineExpose({
  open,
  close,
  setSaving,
})
const [isFullScreen, setIsFullScreen] = useState(false)
const expandIcon = computed(() => {
  return unref(isFullScreen) ? Minus : Plus
})
function toggleFullScreen() {
  const newValue = !unref(isFullScreen)
  setIsFullScreen(newValue)
  emits('fullscreen', newValue)
}
watch(
  () => isFullScreen.value,
  (val: boolean) => {
    setDraggable(!val)
  },
)
</script>

<template>
  <!-- :class="{ 'is-fullscreen': isFullScreen }" -->
  <ElDialog
    v-model="visible"
    :title="title"
    :draggable="draggable"
    destroy-on-close
    :close-on-click-modal="false"
    append-to-body
    v-bind="omit($attrs, 'beforeClose')"
    :show-close="false"
    :fullscreen="isFullScreen"
    style="min-width: 600px;"
    :class="{
      'is-fullscreen': isFullScreen,
      'no-max-height': noMaxHeight,
    }"
  >
    <template #header="{ titleId, titleClass }">
      <slot
        name="header"
        :title-id="titleId"
        :title-class="titleClass"
      >
        <div class="align-center flex">
          <span
            :id="titleId"
            :class="titleClass"
            style="margin: 0"
          >
            {{ title }}
          </span>
          <div
            class="align-center margin-left-auto flex"
            @mousedown.stop
          >
            <ElIcon
              v-if="fullable"
              class="c-pointer"
              style="padding: 6px"
              @click="toggleFullScreen"
            >
              <component :is="expandIcon" />
            </ElIcon>
            <ElIcon
              class="c-pointer"
              style="padding: 6px"
              @click="close"
            >
              <Close />
            </ElIcon>
          </div>
        </div>
      </slot>
    </template>
    <Suspense>
      <AsyncComponent>
        <slot />
      </AsyncComponent>
      <template #fallback>
        <div
          v-loading="true"
          element-loading-custom-class="global-loading"
          style="min-height: 200px"
        />
      </template>
    </Suspense>
    <template v-if="showFooter" #footer>
      <slot name="footer">
        <span class="dialog-footer">
          <ElButton v-if="showCancelButton" @click="close">
            {{ cancelButtonText }}
          </ElButton>
          <ElButton
            v-if="showConfirmButton"
            type="primary"
            :loading="needSaving && saving"
            @click="confirmHandler"
          >
            {{ confirmButtonText }}
          </ElButton>
        </span>
      </slot>
    </template>
  </ElDialog>
</template>

<style lang="scss" scoped>
.el-icon {
  color: var(--el-text-color-secondary);
  &:hover {
    color: var(--el-text-color-regular);
  }
}
</style>

<style>
.is-fullscreen {
  position: absolute !important;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  transform: none !important;
  display: flex;
  flex-direction: column;
}
.is-fullscreen .el-dialog__body {
  flex: 1;
  max-height: none;
}
.no-max-height .el-dialog__body {
  max-height: none !important;
}
</style>
